#pragma once

#include <string>
#include "NavRadarProtocol.h"

class SimRadarController
{
public:
    SimRadarController();
    ~SimRadarController();

    //-----------------------------------------------------------------------------------
    //! Set the new range in the radar
    //! \param range_m The new range expressed in meters
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetRange(uint32_t range_m);
    //-----------------------------------------------------------------------------------
    //! Set the transmission state of the radar. This will also start the scanner rotating
    //! \param state The new state
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetTransmit1(bool state);
    static std::string SetTransmit2(bool state);
    //-----------------------------------------------------------------------------------
    //! Set the gain control
    //! \param type The type of gain can be: eUserGainManual (in this situation the 'level'
    //!     value will be applied), or eUserGainAuto (the radar will work in automatic
    //!     gain mode)
    //! \param level The value to use in manual gain mode (0-255) 
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetGain(Navico::Protocol::NRP::eUserGainManualAuto type, uint8_t level);
    //-----------------------------------------------------------------------------------
    //! Send a client watch-dog kick, to make sure the radar doesn't stop sending spokes.
    //! \return True if the operation was successful
    //-----------------------------------------------------------------------------------
    static std::string SendClientWatchdog();
    //---------------------------------------------------------------------------
    //! Set the use mode
    //! \param mode Selected use mode
    //! \return True if the operation was successful
    //---------------------------------------------------------------------------
    static std::string SetUseMode(Navico::Protocol::NRP::eUseMode mode);

    //-----------------------------------------------------------------------------------
    //! Set the sea clutter level
    //! \param type The type of sea clutter can be: eUserGainManual (in this situation
    //!     the 'level' value will be applied), eUserGainAutoHarbour (the radar will
    //!     work in auto mode optimised for Harbour situations), or eUserGainAutoOffshore
    //!     (the radar will work in auto mode optimised for offshore situations).
    //! \param level The value to use in eUserGainManual mode (0-255) 
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetSeaClutter(Navico::Protocol::NRP::eUserGainManualAuto type, uint8_t level);

    //---------------------------------------------------------------------------
    //! Set the sea clutter level
    //! \param type The type of sea clutter can be: eUserGainManual (in this 
    //! situation the \param level value will be applied), eUserGainAuto
    //! (the radar will work in auto mode).
    //! \param level It is the manual gain value (0-255)
    //! \param autoOffset It is the automatic gain offset value (-128-127)
    //! \param valid It is the bit mask for validity of supplied parameters:
    //!     UserGainValid_Mode = update the manual/auto type,
    //!     UserGainValid_Level = update the manual level,
    //!     UserGainValid_Offset = update the auto offset.
    //!     UserGainValid_ALL = update all three parameters.
    //! \return True if the operation was successful
    //---------------------------------------------------------------------------
    static std::string SetSeaClutter(Navico::Protocol::NRP::eUserGainManualAuto type, uint8_t level, int8_t autoOffset,
        Navico::Protocol::NRP::eUserGainValid valid = Navico::Protocol::NRP::UserGainValid_ALL);

    //-----------------------------------------------------------------------------------
    //! Set the type of STC curve that will be applied in automatic sea clutter rejection.
    //! \param type The curve type to use, one of the eStcCurveType enum values.
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetSTCCurveType(Navico::Protocol::NRP::eStcCurveType type);

    //-----------------------------------------------------------------------------------
    //! Set the rain clutter rejection level
    //! \param level The manual gain value (0-255) 
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetRain(uint8_t level);

    //-----------------------------------------------------------------------------------
    //! Set the sidelobe control
    //! \param type The type of gain can be: eUserGainManual (in this situation the 'level'
    //!     value will be applied), or eUserGainAuto (the radar will work in auto gain mode)
    //! \param level It is the manual gain value (0-255) 
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetSideLobe(Navico::Protocol::NRP::eUserGainManualAuto type, uint8_t level);

    //-----------------------------------------------------------------------------------
    //! Set the FTC level
    //! \param level It is the FTC value (0-255) 
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetFTC(uint8_t level);

    //-----------------------------------------------------------------------------------
    //! Set the interference reject level
    //! \param level It is a value between 0 and 3 - 0 disabled, 3 highest rejection
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetInterferenceReject(uint8_t level);

    //-----------------------------------------------------------------------------------
    //! Set level of local-interference reject
    //! \param level Amount of rejection to apply (none 0 to 3 high)
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetLocalIR(uint8_t level);

    //---------------------------------------------------------------------------
    //! Set the Noise Reject level
    //! \param level Amount of noise rejection to apply (none 0 to 3 high) 
    //! \return True if the operation was successful
    //---------------------------------------------------------------------------
    static std::string SetNoiseReject(uint8_t level);

    //---------------------------------------------------------------------------
    //! Set the Beam Sharpening level
    //! \param level Amount of beam-sharpening to apply (none 0-3 high) 
    //! \return True if the operation was successful
    //---------------------------------------------------------------------------
    static std::string SetBeamSharpening(uint8_t level);

    //---------------------------------------------------------------------------
    //! Set the LEDs lighting level
    //! \param level It is a value between 0 and 4, 0 disabled, 4 brightest
    //! \return True if the operation was successful
    //---------------------------------------------------------------------------
    static std::string SetLEDsLevel(uint8_t level);

    //-----------------------------------------------------------------------------------
    //! Selects between normal and fast scanner rotation speeds. Note that other controls,
    //! such as range and noise-reject, can restrict the maximum RPM available to lower
    //! than this setting.
    //! \param level Selects one of the RPM rates: 0 normal/24rpm, 1 36rpm, or 2 48rpm
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetFastScanMode(uint8_t level);

    //-----------------------------------------------------------------------------------
    //! Set target stretch/expansion in SW
    //! \param state If true, the target will appear larger, if false, with normal size
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetTargetStretch(bool state);

    //! \param level Amount of target-stretch to apply (0 none, up-to 3 high)
    //! \return True if the operation was successful
    //-----------------------------------------------------------------------------------
    static std::string SetTargetStretch(uint8_t level);

    //-----------------------------------------------------------------------------------
    //! Set target boost in hardware, changing physical parameters of the radar (pulse 
    //! width or sweep length, for example).
    //! \param level The level of target boost desired. 0 = best target detail, 2 most
    //!     target emphasis.
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetTargetBoost(uint8_t level);


    /////////////////////////////////////////////////////////////////////////////////////
    //  GuardZones
    /////////////////////////////////////////////////////////////////////////////////////

    //-----------------------------------------------------------------------------------
    //! Enable guard zone detection
    //! \param zone Guard zone index/number (0 to cMaxGuardZones-1)
    //! \param state If true, it will be enabled, false it will be disabled
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetGuardZoneEnable(uint8_t zone, bool state);


    //-----------------------------------------------------------------------------------
    //! Sets up the size and location information for a guard zone
    //! \param zone Guard zone index/number (0 to cMaxGuardZones-1)
    //! \param startRange_m Start of the sector, expressed in meters
    //! \param endRange_m End of the sector, expressed in meters
    //! \param bearing_deg Position of centre of the sector, expressed in degrees
    //! \param width_deg Width of the sector, expressed in degrees (use 360 degrees to
    //!     define a circular sector)
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetGuardZoneSetup(uint8_t zone, uint32_t startRange_m, uint32_t endRange_m, uint16_t bearing_deg, uint16_t width_deg);

    //-----------------------------------------------------------------------------------
    //! Sets up the type of alarm for each guard zone
    //! \param zone Guard zone index/number (0 to cMaxGuardZones-1)
    //! \param type  The alarm type: eGZAlarmEntry (0) alarm only on targets entering the
    //!     zone, eGZAlarmExit (1) alarm only on targets exiting, eGZAlarmBoth (2) alarm
    //!     on targets both entering and exiting the zone
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetGuardZoneAlarmSetup(uint8_t zone, Navico::Protocol::NRP::eGuardZoneAlarmType type);

    //-----------------------------------------------------------------------------------
    //! Suppress an alarm coming from guard zone system
    //! \param zone Guard zone index/number (0 to cMaxGuardZones-1)
    //! \param state If false, suppresses the alarm, if true, unsupresses the alarm
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetGuardZoneAlarmSuppress(uint8_t zone, bool state);


    //-----------------------------------------------------------------------------------
    //! Cancels an alarm coming from guard zone system
    //! \param zone Guard zone index/number (0 to cMaxGuardZones-1)
    //! \param type Type of alarm we want to cancel: eGZAlarmEntry (0) or eGZAlarmExit (1)
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetGuardZoneAlarmCancel(uint8_t zone, Navico::Protocol::NRP::eGuardZoneAlarmType type);

    //-----------------------------------------------------------------------------------
    //! Sets up the sensitivity of guard zones
    //! \param level The level of sensitivity. 0 = no sensitivity, 255 = max sensitivity
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetGuardZoneSensitivity(uint8_t level);


    /////////////////////////////////////////////////////////////////////////////////////
    //  Advanced Commands
    /////////////////////////////////////////////////////////////////////////////////////
    //---------------------------------------------------------------------------
    //! If the scanner supports this mode, the scanner can be configured not to
    //! transmit in a specific sector of rotation
    //! \param sectorID sector ID
    //! \param state if false, the sector will be in off state, if true will be 
    //! in on state
    //! \return True if the operation was successful
    //---------------------------------------------------------------------------
    static std::string SetSectorBlanking(uint32_t sectorID, bool state);

    //---------------------------------------------------------------------------
    //! If the scanner supports this mode, the scanner can be configured not to
    //! transmit in a specific sector of rotation
    //! \param sectorID sector ID
    //! \param state if false, the sector will be in off state, if true will be 
    //! in on state
    //! \param startBearing_degrees Start of the sector in degrees
    //! \param endBearing_degrees End of the sector in degrees
    //! \return True if the operation was successful
    //---------------------------------------------------------------------------
    static std::string SetSectorBlankingSetup(uint32_t sectorID, bool state, uint16_t startBearing_degrees, uint16_t endBearing_degrees);


    //------------------------ Query ----------------------------------------------------

    static std::string QueryRadars();

    //-----------------------------------------------------------------------------------
    //! Query all info from a radar
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string QueryAll();
    //-----------------------------------------------------------------------------------
    //! Query mode info from a radar
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string QueryMode();

    //-----------------------------------------------------------------------------------
    //! Query setup info from a radar
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string QuerySetup();

    //-----------------------------------------------------------------------------------
    //! Query advanced info from a radar
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string QueryAdvancedSetup();

    //-----------------------------------------------------------------------------------
    //! Query properties info from a radar
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string QueryProperties();


    //-----------------------------------------------------------------------------------
    //! Query configuration info from a radar
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string QueryConfiguration();

    //---------------------------------------------------------------------------
    //! Query features information from a radar
    //! \return True if the operation was successfully initiated
    //---------------------------------------------------------------------------
    static std::string QueryFeatures();

    //-----------------------------------------------------------------------------------
    //! Set the zero bearing offset
    //! \param bearing_ddeg The offset expressed in 10ths of a degree (deci-degrees)
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetZeroBearingOffset(uint16_t bearing_ddeg);
    //-----------------------------------------------------------------------------------
    //! Sets the radar to use factory defaults
    //! \return True if the operation was successfully initiated
    //-----------------------------------------------------------------------------------
    static std::string SetToFactoryDefaults();
};